from PySide6.QtWidgets import (QVBoxLayout, QHBoxLayout, QFormLayout, QDialog, QWidget, QMenu)
from PySide6.QtCore import Qt
from PySide6.QtGui import QCursor
from .widgets.table_widget import CommonTableWidget
from .widgets.category_tree_combo import CategoryTreeCombo
from .widgets.dialogs import BaseDialog, MessageOverlay
from .widgets.panels import BasePanel
from .widgets.basewidgets import *
from api import api
from common import config, utils

PRODUCT_HEADER_COLUMNS = {"商品编码":{"type":"text",
                                  "text": lambda x: x["code"],
                                  "width": 0.15},
                          "商品名称":{"type":"text",
                                  "color": lambda x: "#0000ff" if not x["status"] else "",
                                  "text": lambda x: x["name"]},
                          "分类":{"type":"text",
                                  "text": lambda x: x["category"]["name"]},
                          "规格":{"type":"text",
                                  "text": lambda x: x["unit"]},
                          "售价":{"type":"text",
                                  "text": lambda x: x['price'],
                                  "sort": "price"},
                          "库存":{"type":"text",
                                  "color": lambda x: "#ff0000" if x["stock"] <= x["lowest_stock"] else "",
                                  "text": lambda x: x["stock"],
                                  "sort": "stock"},
                          "操作":{"type":"action", "width": 0.18}}

class ProductPage(BasePanel):
    def __init__(self):
        super().__init__("商品管理")
        self.categories = {}
        self.setup_ui()
        self.setup_context_menu()
        
    def setup_ui(self):
        # 使用BasePanel中的main_layout而不是创建新的布局
        
        # 搜索和操作区域
        search_widget = SearchPanel()
        search_layout = QHBoxLayout(search_widget)
        
        # 搜索框
        self.search_input = SearchLineEdit(self, "输入商品名称或编码搜索")
        self.search_input.textChanged.connect(self.flush_table)

        # 上架状态
        self.sale_status_combo = NormalComboBox()
        self.sale_status_combo.setItems({"全部状态":"", "上架中":"true", "下架中":"false"})
        self.sale_status_combo.currentTextChanged.connect(self.flush_table)

        # 分类树型选择框
        self.category_combo = CategoryTreeCombo()
        self.category_combo.set_categories({})
        self.category_combo.setFixedWidth(200)
        self.category_combo.selectedChanged.connect(self.flush_table)
        
        # 低库存过滤
        self.low_stock_checkbox = NormalCheckBox(self, "仅显示库存告警项")
        self.low_stock_checkbox.clicked.connect(self.flush_table)
        
        # 添加分类按钮
        add_category_btn = GreenPushButton("添加分类")
        add_category_btn.clicked.connect(self.show_add_category_dialog)
        
        # 添加商品按钮
        add_btn = BluePushButton("添加商品")
        add_btn.clicked.connect(self.show_add_product_dialog)
        
        search_layout.addWidget(self.search_input)
        search_layout.addWidget(self.sale_status_combo)
        search_layout.addWidget(self.category_combo)
        search_layout.addWidget(self.low_stock_checkbox)
        search_layout.addStretch()
        search_layout.addWidget(add_category_btn)
        search_layout.addWidget(add_btn)
        
        self.main_layout.addWidget(search_widget)
        
        # 商品表格
        table_widget = QWidget()
        table_widget.setObjectName("productTable")
        table_layout = QVBoxLayout(table_widget)
        
        self.product_table = CommonTableWidget(headers=PRODUCT_HEADER_COLUMNS)
        self.product_table.pageChanged.connect(self.flush_table)
        self.product_table.set_description("初始库存只能在添加的时候设置, 添加以后不可修改, 只能通过采购入库来增加库存，"
                                           "已经下架的商品名字会显示<span style='color: #0000ff;'>蓝色</span>，"
                                           "库存低于或者等于告警库存的商品库存会显示<span style='color: #ff0000;'>红色</span>。"
                                           "库存数量、价格可排序。")
        self.product_table.pageSizeChanged.connect(self.flush_table)
        self.product_table.sortChanged.connect(self.flush_table)

        table_layout.addWidget(self.product_table)
        self.main_layout.addWidget(table_widget)

    def setup_context_menu(self):
        super().setup_context_menu()
        self.product_table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.product_table.customContextMenuRequested.connect(self.show_context_menu)

    def add_extra_context_menus(self, menu, pos):
        menu.addSeparator()
        
        add_category_action = menu.addAction("添加分类")
        add_category_action.triggered.connect(self.show_add_category_dialog)
        
        add_product_action = menu.addAction("添加商品")
        add_product_action.triggered.connect(self.show_add_product_dialog)
        
        # 判断是否在表格中点击及点击的位置
        sender = self.sender()
        if sender == self.product_table:
            # 获取点击的行
            item = self.product_table.itemAt(pos)
            if item:
                row = item.row()
                product_data = self.product_table.get_row_data(row)
                
                menu.addSeparator()
                
                # 商品操作子菜单
                operations_menu = menu.addMenu("商品操作")
                
                # 根据商品状态添加上架/下架操作
                if product_data["status"]:
                    status_action = operations_menu.addAction("下架商品")
                else:
                    status_action = operations_menu.addAction("上架商品")
                status_action.triggered.connect(lambda: self.update_product_status(row))
                
                edit_action = operations_menu.addAction("编辑商品")
                edit_action.triggered.connect(lambda: self.edit_product(row))
                
                delete_action = operations_menu.addAction("删除商品")
                delete_action.triggered.connect(lambda: self.delete_product(row))
                
                menu.addSeparator()
                
                # 商品信息子菜单
                info_menu = menu.addMenu("商品信息")
                info_menu.addAction(f"商品编码: {product_data['code']}")
                info_menu.addAction(f"商品名称: {product_data['name']}")
                info_menu.addAction(f"商品分类: {product_data['category']['name']}")
                info_menu.addAction(f"商品规格: {product_data['unit']}")
                info_menu.addAction(f"商品售价: {product_data['price']}({config.CURRENCY_UNIT})")
                info_menu.addAction(f"当前库存: {product_data['stock']}")
                info_menu.addAction(f"告警库存: {product_data['lowest_stock']}")
                info_menu.addAction(f"上架时间：{utils.format_datetime(product_data['created_at'])}")
                if product_data["updated_at"]:
                    info_menu.addAction(f"更新时间：{utils.format_datetime(product_data['updated_at'])}")

                # 供应商
                menu.addSeparator()
                suppliers_menu = menu.addMenu("供应商")
                if "suppliers" in product_data:
                    suppliers = product_data["suppliers"]
                else:
                    suppliers = api.get_product_suppliers(product_data["id"])["suppliers"]
                    product_data["suppliers"] = suppliers
                for supplier in suppliers:
                    suppliers_menu.addAction(f"{supplier['name']} : {supplier['cost_price']}({config.CURRENCY_UNIT})")
                if not suppliers:
                    suppliers_menu.addAction("暂无供应商")
    
    def update_category_combo(self):
        self.category_combo.set_categories(utils.parse_category_tree(self.categories))

    def flush_table(self):
        products = api.get_products(search=self.search_input.text(),
                                    category_id=self.category_combo.get_selected_id(),
                                    status=self.sale_status_combo.currentData(),
                                    low_stock_only=self.low_stock_checkbox.isChecked(),
                                    page=self.product_table.current_page,
                                    per_page=self.product_table.page_size,
                                    order_by=self.product_table.sort_string)
        if not products:
            return
        self.product_table.clearContents()
        self.product_table.setRowCount(0)
        self.product_table.set_total_items(products["count"])
        row_count = len(products["items"])
        self.product_table.setRowCount(row_count)
        for i in range(row_count):
            self.product_table.set_row_data(i, products["items"][i])
            self.product_table.add_action_buttons(i,
                [{"text": "下架" if products["items"][i]["status"] else "上架",
                  "callback": self.update_product_status,
                  "objectName": "editButton" if products["items"][i]["status"] else "deleteButton"},
                 {"text": "编辑", "callback": self.edit_product},
                 {"text": "删除", "callback": self.delete_product, "objectName": "deleteButton"}])

    def load_data(self):
        self.categories = api.get_categories()
        self.update_category_combo()
        self.flush_table()

    def update_product_status(self, row):
        row_data = self.product_table.get_row_data(row)
        product = api.update_product(row_data["code"], status=not row_data["status"])
        self.product_table.set_row_data(row, product)
        self.product_table.add_action_buttons(row,
                [{"text": "下架" if product["status"] else "上架",
                  "callback": self.update_product_status,
                  "objectName": "editButton" if product["status"] else "deleteButton"},
                 {"text": "编辑", "callback": self.edit_product},
                 {"text": "删除", "callback": self.delete_product, "objectName": "deleteButton"}])

    def edit_product(self, row):
        row_data = self.product_table.get_row_data(row)
        code = row_data["code"]
        dialog = AddProductDialog(self.categories, self, code)
        if dialog.exec() == QDialog.Accepted:
            product = api.update_product(code, name=dialog.name_input.text(),
                                        category_id=dialog.category_combo.get_selected_id(),
                                        unit=dialog.spec_input.text(),
                                        price=dialog.price_input.value(),
                                        lowest_stock=dialog.lowest_stock_input.value(),
                                        description=dialog.description_input.toPlainText())
            # 更新表格数据
            self.product_table.set_row_data(row, product)
            MessageOverlay.info(self, "商品信息更新成功")
    
    def delete_product(self, row):
        if MessageOverlay.question(self, "确定要删除这个商品吗？") == MessageOverlay.ACCEPTED:
            api.delete_product(self.product_table.get_row_data(row)["code"])
            self.flush_table()
            MessageOverlay.info(self, "商品删除成功")
    
    def show_add_category_dialog(self):
        dialog = AddCategoryDialog(self.categories, self)
        if dialog.exec() == QDialog.Accepted:
            new_category = dialog.category_input.text()
            parent_category = dialog.parent_category_combo.get_selected_id()
            api.add_category(new_category, parent_category)
            self.categories = api.get_categories()
            self.update_category_combo()
            MessageOverlay.info(self, f"已添加新分类: {new_category}")
    
    def show_add_product_dialog(self):
        dialog = AddProductDialog(self.categories, self, None, self.category_combo.get_selected_id())
        if dialog.exec() == QDialog.Accepted:
            product_name = dialog.name_input.text()
            product_category = dialog.category_combo.get_selected_id()
            product_spec = dialog.spec_input.text()
            product_price = dialog.price_input.value()
            product_stock = 0 #dialog.stock_input.value()
            lowest_stock = dialog.lowest_stock_input.value()
            description = dialog.description_input.text()

            # 添加到表格
            api.add_product(product_name, product_category, product_spec, product_price, product_stock, lowest_stock, description)
            self.flush_table()
            
            MessageOverlay.info(self, "商品添加成功")

class AddProductDialog(BaseDialog):
    def __init__(self, categories, parent=None, code=None, selected_category_id=None):
        super().__init__(parent)
        self.categories = categories
        self.code = code
        self.setup_ui()
        
        # 如果是编辑模式，填充现有数据
        if code:
            product = api.get_product(code)
            self.code_input.setText(product["code"])
            self.name_input.setText(product["name"])
            self.category_combo.set_selected_id(product["category_id"])
            self.spec_input.setText(product["unit"])
            self.price_input.setValue(product["price"])
            self.stock_input.setValue(product["stock"])
            self.lowest_stock_input.setValue(product["lowest_stock"])
            self.description_input.setText(product["description"])
        else:
            self.category_combo.set_selected_id(selected_category_id)

    def setup_ui(self):
        self.setWindowTitle("添加商品" if self.code is None else "编辑商品")
        self.setMinimumWidth(500)
        
        layout = QVBoxLayout(self)
        
        # 表单布局
        form_layout = QFormLayout()
        form_layout.setSpacing(8)
        
        # 商品编码 TODO: 扫码枪扫码
        self.code_input = NormalLineEdit()
        self.code_input.setPlaceholderText("自动生成")
        self.code_input.setReadOnly(True)
        form_layout.addRow("商品编码:", self.code_input)
        
        # 商品名称
        self.name_input = NormalLineEdit()
        form_layout.addRow("商品名称:", self.name_input)
        
        # 商品分类
        self.category_combo = CategoryTreeCombo()
        self.category_combo.set_categories(utils.parse_category_tree(self.categories, {}))
        form_layout.addRow("商品分类:", self.category_combo)
        
        # 商品规格
        self.spec_input = NormalLineEdit()
        form_layout.addRow("商品规格:", self.spec_input)
        
        # 售价
        self.price_input = NormalFloatSpinBox()
        form_layout.addRow("售价:", self.price_input)
        
        # 当前库存
        self.stock_input = NormalIntSpinBox()
        self.stock_input.setReadOnly(True)
        form_layout.addRow("当前库存:", self.stock_input)

        # 最低库存
        self.lowest_stock_input = NormalIntSpinBox()
        form_layout.addRow("告警库存:", self.lowest_stock_input)

        # 描述
        self.description_input = NormalTextEdit()
        form_layout.addRow("描述:", self.description_input)
        
        layout.addLayout(form_layout)
        layout.addLayout(self.create_button_layout(self.validate_and_accept))
    
    def validate_and_accept(self):        
        if not self.name_input.text():
            MessageOverlay.warning(self, "请输入商品名称")
            return
        
        if not self.spec_input.text():
            MessageOverlay.warning(self, "请输入商品规格")
            return
        
        if self.price_input.value() <= 0:
            MessageOverlay.warning(self, "售价必须大于0")
            return
        
        self.accept()

class AddCategoryDialog(BaseDialog):
    def __init__(self, categories, parent=None):
        super().__init__(parent)
        self.categories = categories
        self.setup_ui()
    
    def setup_ui(self):
        self.setWindowTitle("添加分类")
        self.setMinimumWidth(400)
        
        layout = QVBoxLayout(self)
        
        # 表单布局
        form_layout = QFormLayout()
        form_layout.setSpacing(8)
        
        # 父分类选择
        self.parent_category_combo = CategoryTreeCombo()
        self.parent_category_combo.set_categories(utils.parse_category_tree(self.categories))
        form_layout.addRow("父分类:", self.parent_category_combo)
        
        # 新分类名称
        self.category_input = NormalLineEdit()
        form_layout.addRow("分类名称:", self.category_input)
        
        layout.addLayout(form_layout)

        layout.addLayout(self.create_button_layout(self.validate_and_accept))
    
    def validate_and_accept(self):        
        if not self.category_input.text():
            MessageOverlay.warning(self, "请输入分类名称")
            return
        
        self.accept()
